package com.airsystem.pos.bengkel.view;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;

import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import org.apache.log4j.Logger;

import com.airsystem.pos.bengkel.controller.MenuController;
import com.airsystem.pos.bengkel.controller.ServiceOrderController;
import com.airsystem.pos.bengkel.interfaces.IComboState;
import com.airsystem.pos.bengkel.util.TextUtil;

/**
 * @author Budi Oktaviyan <budi.oktaviyan@icloud.com>
 */
public class ServiceOrder extends ServiceOrderController {
	private static final Logger LOG = Logger.getLogger(ServiceOrder.class.getSimpleName());

	public ServiceOrder(MenuController menuController) {
		super();

		this.menuController = menuController;
		initComponents();
		setup();
		load();
	}

	private void initComponents() {
		setTitle("Jasa Service");
		setFrameIcon(new ImageIcon(getClass().getResource("/images/jasay.png")));
		setIconifiable(true);
		setMaximizable(true);
		setClosable(true);
		scrollPane.setViewportView(basePanel);

		baseLayout.columnWidths = new int[] { 0 };
		baseLayout.rowHeights = new int[] { 0 };
		baseLayout.columnWeights = new double[] { 1.0 };
		baseLayout.rowWeights = new double[] { 1.0 };
		getContentPane().setLayout(baseLayout);

		panelLayout.columnWidths = new int[] { 150, 300, 0 };
		panelLayout.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
		panelLayout.columnWeights = new double[] { 0.0, 1.0, 1.0 };
		panelLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0 };
		basePanel.setLayout(panelLayout);

		tanggalLabel.setFont(new Font("Verdana", 0, 12));
		tanggalLabel.setText("Tanggal");

		namaLabel.setFont(new Font("Verdana", 0, 12));
		namaLabel.setText("Nama Pelanggan");

		kendaraanLabel.setFont(new Font("Verdana", 0, 12));
		kendaraanLabel.setText("Kendaraan");

		nopolLabel.setFont(new Font("Verdana", 0, 12));
		nopolLabel.setText("No.Polisi");

		serviceLabel.setFont(new Font("Verdana", 0, 12));
		serviceLabel.setText("Jenis Service");

		sparepartLabel.setFont(new Font("Verdana", 0, 12));
		sparepartLabel.setText("Sparepart");

		sparepartUsedLabel.setFont(new Font("Verdana", 0, 12));
		sparepartUsedLabel.setText("Sparepart Terpakai");

		hargaLabel.setFont(new Font("Verdana", 0, 12));
		hargaLabel.setText("Harga");

		kilometerLabel.setFont(new Font("Verdana", 0, 12));
		kilometerLabel.setText("Kilometer");

		metodeLabel.setFont(new Font("Verdana", 0, 12));
		metodeLabel.setText("Metode Pembayaran");

		tanggalChooser.setDateFormatString("d MMMM yyyy");
		((JTextField) tanggalChooser.getDateEditor().getUiComponent()).setEditable(false);

		namaCombo.setFont(new Font("Verdana", 0, 12));
		namaCombo.addItemListener(new ItemChangedListener<PelangganSelectedState>(PelangganSelectedState.class));

		kendaraanCombo.setFont(new Font("Verdana", 0, 12));
		kendaraanCombo.addItemListener(new ItemChangedListener<KendaraanSelectedState>(KendaraanSelectedState.class));

		serviceCombo.setFont(new Font("Verdana", 0, 12));
		serviceCombo.addItemListener(new ItemChangedListener<LayananSelectedState>(LayananSelectedState.class));

		sparepartCombo.setFont(new Font("Verdana", 0, 12));
		sparepartCombo.addItemListener(new ItemChangedListener<SparepartSelectedState>(SparepartSelectedState.class));

		pembayaranCombo.setFont(new Font("Verdana", 0, 12));
		pembayaranCombo.setModel(new DefaultComboBoxModel(COMBOS));

		nopolField.setFont(new Font("Verdana", 0, 12));
		nopolField.setColumns(15);
		nopolField.setEditable(false);

		sparepartUsedField.setFont(new Font("Verdana", 0, 12));
		sparepartUsedField.setColumns(15);
		sparepartUsedField.setDocument(new TextUtil(3, TextUtil.NUMBER));
		sparepartUsedField.getDocument().addDocumentListener(new DocumentListener() {
					public void removeUpdate(DocumentEvent event) {
						doUpdateHarga();
					}

					public void insertUpdate(DocumentEvent event) {
						doUpdateHarga();
					}

					public void changedUpdate(DocumentEvent event) {
						doUpdateHarga();
					}

					public void doUpdateHarga() {
						if (!(comboState instanceof SparepartInputState)) {
							comboState = new SparepartInputState();
						}

						comboState.prepareHarga();
					}
				});

		hargaField.setFont(new Font("Verdana", 0, 12));
		hargaField.setColumns(15);
		hargaField.setEditable(false);

		kilometerField.setFont(new Font("Verdana", 0, 12));
		kilometerField.setColumns(15);
		kilometerField.setDocument(new TextUtil(6, TextUtil.NUMBER));

		idField.setFont(new Font("Verdana", 0, 12));
		idField.setColumns(5);
		idField.setVisible(false);

		buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 10));

		searchButton.setIcon(new ImageIcon(getClass().getResource("/images/search.png")));
		searchButton.setFont(new Font("Verdana", 1, 12));
		searchButton.setText("CARI");

		addButton.setIcon(new ImageIcon(getClass().getResource("/images/add.png")));
		addButton.setFont(new Font("Verdana", 1, 12));
		addButton.setText("TAMBAH");
		buttonPanel.add(addButton);

		submitButton.setIcon(new ImageIcon(getClass().getResource("/images/submit.png")));
		submitButton.setFont(new Font("Verdana", 1, 12));
		submitButton.setText("KIRIM");
		buttonPanel.add(submitButton);

		updateButton.setIcon(new ImageIcon(getClass().getResource("/images/update.png")));
		updateButton.setFont(new Font("Verdana", 1, 12));
		updateButton.setText("UBAH");
		buttonPanel.add(updateButton);

		deleteButton.setIcon(new ImageIcon(getClass().getResource("/images/delete.png")));
		deleteButton.setFont(new Font("Verdana", 1, 12));
		deleteButton.setText("HAPUS");
		buttonPanel.add(deleteButton);

		cancelButton.setIcon(new ImageIcon(getClass().getResource("/images/cancel.png")));
		cancelButton.setFont(new Font("Verdana", 1, 12));
		cancelButton.setText("BATAL");
		buttonPanel.add(cancelButton);

		initServices();

		searchButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				searchButtonActionPerformed(evt);
			}
		});

		addButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				addButtonActionPerformed(evt);
			}
		});

		submitButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				submitButtonActionPerformed(evt);
			}
		});

		updateButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				updateButtonActionPerformed(evt);
			}
		});

		deleteButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				deleteButtonActionPerformed(evt);
			}
		});

		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				cancelButtonActionPerformed(evt);
			}
		});

		basePanel.add(tanggalLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(30, 70, 20, 30), 0, 0));
		basePanel.add(namaLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(kendaraanLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(nopolLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(serviceLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(sparepartLabel, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(sparepartUsedLabel, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(hargaLabel, new GridBagConstraints(0, 8, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(kilometerLabel, new GridBagConstraints(0, 9, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(metodeLabel, new GridBagConstraints(0, 10, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 70, 20, 30), 0, 0));
		basePanel.add(tanggalChooser, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(30, 20, 20, 30), 0, 0));
		basePanel.add(namaCombo, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(kendaraanCombo, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(nopolField, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(serviceCombo, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(sparepartCombo, new GridBagConstraints(1, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(sparepartUsedField, new GridBagConstraints(1, 7, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(hargaField, new GridBagConstraints(1, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(kilometerField, new GridBagConstraints(1, 9, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(pembayaranCombo, new GridBagConstraints(1, 10, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 20, 20, 30), 0, 0));
		basePanel.add(searchButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(30, 20, 20, 0), 0, 0));
		basePanel.add(buttonPanel, new GridBagConstraints(0, 11, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
		basePanel.add(idField, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 20, 20, 0), 0, 0));

		getContentPane().add(scrollPane, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));

		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		setBounds((screenSize.width - 800) / 2, (screenSize.height - 700) / 2, 800, 600);
	}

	private void initServices() {
		tableserviceScroll.setViewportView(tableServices);
		tableServices.setFont(new Font("Verdana", 0, 12));
		tableServices.setModel(tableModel);

		tableServices.getTableHeader().setReorderingAllowed(false);
		tableServices.getColumnModel().getColumn(0).setPreferredWidth(250);
		tableServices.getColumnModel().getColumn(1).setPreferredWidth(450);
		tableServices.getColumnModel().getColumn(2).setPreferredWidth(250);
		tableServices.getColumnModel().getColumn(3).setPreferredWidth(250);
		tableServices.getColumnModel().getColumn(4).setPreferredWidth(300);

		/* Hide Column */
		tableServices.getColumnModel().getColumn(5).setMaxWidth(0);
		tableServices.getColumnModel().getColumn(5).setMinWidth(0);
		tableServices.getColumnModel().getColumn(5).setPreferredWidth(0);

		tableServices.setPreferredScrollableViewportSize(new Dimension(150, 150));
		tableServices.setFillsViewportHeight(true);

		tableServices.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent evt) {
				tableServicesMouseClicked(evt);
			}
		});

		fieldPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 20));

		totalLabel.setFont(new Font("Verdana", 0, 12));
		totalLabel.setText("Total Harga");
		fieldPanel.add(totalLabel);

		totalField.setFont(new Font("Verdana", 0, 12));
		totalField.setColumns(15);
		totalField.setEditable(false);
		fieldPanel.add(totalField);

		basePanel.add(tableserviceScroll, new GridBagConstraints(0, 12, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 1, 1, 1), 0, 0));
		basePanel.add(fieldPanel, new GridBagConstraints(0, 13, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 30, 0, 0), 0, 0));
	}

	private void searchButtonActionPerformed(ActionEvent evt) {
		search();
	}

	private void tableServicesMouseClicked(MouseEvent evt) {
		if (evt.getClickCount() == 2 && tableServices.getRowCount() != 0) {
			row = tableServices.getSelectedRow();
			isGridClicked = true;

			init();
		}
	}

	private void addButtonActionPerformed(ActionEvent evt) {
		add();
	}

	private void submitButtonActionPerformed(ActionEvent evt) {
		submit();
	}

	private void updateButtonActionPerformed(ActionEvent evt) {
		edit();
	}

	private void deleteButtonActionPerformed(ActionEvent evt) {
		remove();
	}

	private void cancelButtonActionPerformed(ActionEvent evt) {
		cancel();
	}

	private final class ItemChangedListener<T extends IComboState> implements ItemListener {
		private final Class<T> clazz;

		public ItemChangedListener(Class<T> clazz) {
			this.clazz = clazz;
		}

		public void itemStateChanged(ItemEvent evt) {
			if (evt.getStateChange() != ItemEvent.SELECTED) {
				return;
			}

			try {
				comboState = (IComboState) clazz.getConstructors()[0].newInstance(ServiceOrder.this);
				setSelected(evt.getItem());

				if (isPelangganSelectedState()) {
					comboState.prepareKendaraan();
				} else if (isKendaraanSelectedState()) {
					comboState.prepareNopol();
					comboState.prepareService();
				} else if (isLayananSelectedState()) {
					comboState.prepareSparepart();
					comboState.prepareHarga();
				} else if (isSparepartSelectedState()) {
					comboState.prepareHarga();
				}
			} catch (InstantiationException e) {
				LOG.error(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				LOG.error(e.getMessage(), e);
			} catch (IllegalArgumentException e) {
				LOG.error(e.getMessage(), e);
			} catch (InvocationTargetException e) {
				LOG.error(e.getMessage(), e);
			} catch (SecurityException e) {
				LOG.error(e.getMessage(), e);
			}
		}

		private final boolean isPelangganSelectedState() {
			return this.clazz.equals(PelangganSelectedState.class);
		}

		private final boolean isKendaraanSelectedState() {
			return this.clazz.equals(KendaraanSelectedState.class);
		}

		private final boolean isLayananSelectedState() {
			return this.clazz.equals(LayananSelectedState.class);
		}

		private final boolean isSparepartSelectedState() {
			return this.clazz.equals(SparepartSelectedState.class);
		}
	}
}